package com.lincoln.Client.game;

import com.lincoln.Client.context.*;
import com.lincoln.Client.reptile.BaseReptile;
import com.lincoln.framework.entity.Betting;
import com.lincoln.framework.entity.Game;
import com.lincoln.framework.entity.Member;
import com.lincoln.framework.service.BettingService;
import com.lincoln.framework.service.GameService;
import com.lincoln.framework.service.MemberService;
import com.lincoln.framework.spring.SpringContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 北京28,五分钟一次
 */
public class Beijing28Game extends Thread {
    public Logger logger = LoggerFactory.getLogger(getClass());

    public long time = 0;//当前第xx期

    public long lastGameNo;//上一期游戏期数
    public long gameNo;//当前游戏期数
    public long nextGameNo;//下一期游戏期数

    public Game game;

    public Date nextDate;//下次开奖时间

    public long timeLeft = 0;//剩余开奖时间(s)

    public int result1;
    public int result2;
    public int result3;
    /**
     * 当前使用的爬虫
     */
    public BaseReptile reptile;

    /**
     */
    public Beijing28Game() {
    }

    @Override
    public void run() {
        newRound();
    }

    public void newRound() {
        time++;
        //刷新列表
        FrameContext.main.mainCenterPanel.flashAllUser();
        FrameContext.main.mainCenterPanel.flashGameList();
        //强制让上一场游戏停止
        GameService gameService = SpringContextUtil.getBean(GameService.class);
        MemberService memberService = SpringContextUtil.getBean(MemberService.class);
        Game last = gameService.getNewestGame();
        if (last != null && (last.getEndTime() == null || last.getEndTime().getTime() > new Date().getTime())) {
            last.setEndTime(new Date());
            gameService.save(last);
        }
        BettingService bettingService = SpringContextUtil.getBean(BettingService.class);
        //在数据库中找到所有未处理的下注,并将其设为未中奖
        bettingService.unWinAllNoDeal();
        //删除所有未开奖的记录
        gameService.deleteAllNoEnd();
        if (GameContext.autoStopBetting) {//自动开奖
            if (!GameContext.canPlay || !GameContext.autoStopBetting) {
                logger.info("系统关闭了");
                return;
            }
            //当轮第一次取当前开奖信息
            if (!requestGameInfo()) {
                GameContext.autoStopBetting = false;
                FrameContext.main.mainCenterPanel.down.stopCai.setText("自动开奖");
                if (time == 1) {//第一次就获取失败时,重开一次
                    time = 0;
                    newRound();
                }
                return;
            }
            RobotContext.sendMsg("第" + this.gameNo + "期游戏已经开启,欢迎下注!");
            if (time > 1) {//第一次为测试轮次
                //允许下注
                GameContext.canBetting = true;
                GameContext.beforeStopBetting = true;
            } else {
                GameContext.canBetting = false;
                GameContext.beforeStopBetting = true;
                RobotContext.sendMsg(SettingContext.getInofoSetting().getProperty("test.text", ""));
            }
            long nextGameNo = this.nextGameNo;
            long timeLeft = this.timeLeft;
            long lastGameNo = 0;
            Integer result1 = this.result1;
            Integer result2 = this.result2;
            Integer result3 = this.result3;
            int error_time = 0;//爬虫错误次数
            while (lastGameNo != this.gameNo) {//等待开奖
                try {
                    Map<String, Object> map = reptile();
                    if (!GameContext.canPlay || !GameContext.autoStopBetting) {
                        logger.info("手动停猜了");
                        return;
                    }
                    nextGameNo = (long) map.get("nextGameNo");
                    nextGameNo++;//下一轮的期号(不一定对,但由于上一句是取当前轮)
                    timeLeft = (int) map.get("time");
                    lastGameNo = (long) map.get("lastGameNo");
                    result1 = (int) map.get("result1");
                    result2 = (int) map.get("result2");
                    result3 = (int) map.get("result3");
                } catch (Exception e) {
                    error_time++;
                    if (error_time < 3) {
                        continue;
                    } else {
                        GameContext.doStopBetting();
                        return;
                    }
                }
                this.timeLeft = timeLeft;
                nextDate = new Date(new Date().getTime() + this.timeLeft * 1000);
                //此处要读取停猜时间前要执行的提示数据
                int beforeStopTime = 0;//多少秒停猜默认值30
                beforeStopTime = Integer.parseInt(SettingContext.getInofoSetting().getProperty("tingcai.qian", "0"));
                //此处要读取停猜时间数据
                int beforeTime = 30;//多少秒停猜默认值30
                beforeTime = Integer.parseInt(SettingContext.getInofoSetting().getProperty("tingcai.kaijiangqian", "30"));
                if (timeLeft <= beforeStopTime + beforeTime) {
                    //停止下注前XX秒发送提示
                    GameContext.beforeStopBetting();
                }

                if (timeLeft <= beforeTime) {
                    //停止下注
                    GameContext.stopBetting();
                }
            }
            //到这说明开奖了
            kaijiang(result1, result2, result3);
        } else {//手动开奖
            this.lastGameNo = GameNoUtils.getBeiJingCurrGameNo() - 1;
            this.gameNo = GameNoUtils.getBeiJingCurrGameNo();
            this.nextGameNo = this.gameNo + 1;
            this.timeLeft = GameNoUtils.getBeiJingCurrGameLeftTime();
            nextDate = new Date(new Date().getTime() + this.timeLeft * 1000);
            this.result1 = -1;
            this.result2 = -1;
            this.result3 = -1;
            game = new Game();
            game.setGameNo(this.gameNo);
            game.setStartTime(new Date());
            gameService.save(game);
            RobotContext.sendMsg("第" + this.gameNo + "期游戏已经开启,欢迎下注!");
            if (time > 1) {//第一次为测试轮次
                //允许下注
                GameContext.canBetting = true;
                GameContext.beforeStopBetting = true;
            } else {
                GameContext.canBetting = false;
                GameContext.beforeStopBetting = true;
                RobotContext.sendMsg(SettingContext.getInofoSetting().getProperty("test.text", ""));
            }
        }


    }


    /**
     * 通过爬虫获取当前开奖的期号,取到后保存,成功返回true,失败返回false
     */
    public boolean requestGameInfo() {
        try {
            GameService gameService = SpringContextUtil.getBean(GameService.class);
            //当轮第一次取当前开奖信息
            Map<String, Object> map = reptile();
            long nextGameNo = 0;
            try{
                nextGameNo = (long) map.get("nextGameNo");
            }catch (Exception e){
                nextGameNo = Long.parseLong((String) map.get("nextGameNo"));
            }
            if(nextGameNo == 0){
                throw new Exception("cuowu");
            }
            int time = -1;
            try{
                time = (int) map.get("time");
            }catch (Exception e){
                time = Integer.parseInt((String) map.get("time"));
            }
            if(time == -1){
                throw new Exception("cuowu");
            }
            long lastGameNo = 0;
            try{
                lastGameNo = (long) map.get("lastGameNo");
            }catch (Exception e){
                lastGameNo = Long.parseLong((String) map.get("lastGameNo"));
            }
            if(lastGameNo == 0){
                throw new Exception("cuowu");
            }
            this.lastGameNo = lastGameNo;
            this.gameNo = nextGameNo;
            this.nextGameNo = this.gameNo + 1;
            this.timeLeft = time;
            nextDate = new Date(new Date().getTime() + this.timeLeft * 1000);
            this.result1 = -1;
            try{
                result1 = (int) map.get("result1");
            }catch (Exception e){
                result1 = Integer.parseInt((String) map.get("result1"));
            }
            if(result1 == -1){
                throw new Exception("cuowu");
            }

            this.result2 = -1;
            try{
                result2 = (int) map.get("result2");
            }catch (Exception e){
                result2 = Integer.parseInt((String) map.get("result2"));
            }
            if(result2 == -1){
                throw new Exception("cuowu");
            }

            this.result3 = -1;
            try{
                result3 = (int) map.get("result3");
            }catch (Exception e){
                result3 = Integer.parseInt((String) map.get("result3"));
            }
            if(result3 == -1){
                throw new Exception("cuowu");
            }
            this.result3 = (int) map.get("result3");
            game = new Game();
            game.setGameNo(nextGameNo);
            game.setStartTime(new Date());
            gameService.save(game);
        } catch (Exception e) {
            logger.error("爬取信息错误,切换手动开奖");
            return false;
        }
        return true;
    }

    /**
     * 开奖
     */
    public void kaijiang(int result1, int result2, int result3) {
        //开奖前执行
        GameContext.beforeOpenGame();
        this.result1 = result1;
        this.result2 = result2;
        this.result3 = result3;
        GameService gameService = SpringContextUtil.getBean(GameService.class);
        BettingService bettingService = SpringContextUtil.getBean(BettingService.class);
        MemberService memberService = SpringContextUtil.getBean(MemberService.class);
        Game game = gameService.getGameByNo(this.gameNo, false);
        game.setEndTime(new Date());
        game.setResult1(result1);
        game.setResult2(result2);
        game.setResult3(result3);
        gameService.save(game);
        this.game = game;
        logger.info("第" + this.gameNo + "期结果:" + result1 + "+" + result2 + "+" + result3);
        List<Betting> bettings = bettingService.queryBettingByGame(game.getId());
        for (Betting betting : bettings) {
            double score = dealBettingResult(betting, game);//
            if (score > 0) {//赢钱
                betting.setResult(Betting.RESULT_WIN);
                betting.setWin(score);
                Member member = betting.getMember();
                member.setEarn(member.getEarn() + score);
                memberService.save(member);
                bettingService.save(betting);
            } else {//输了
                betting.setWin(new Double(0));
                betting.setResult(Betting.RESULT_LOSE);
                bettingService.save(betting);
            }
        }
        //开奖信息
        GameContext.openGame();
        //发送积分列表
        GameContext.sendMemberScoreInfo();


        //发广告
        int ad1 = Integer.parseInt(SettingContext.getInofoSetting().getProperty("ad.1.cycle", "0"));
        int ad2 = Integer.parseInt(SettingContext.getInofoSetting().getProperty("ad.2.cycle", "0"));
        int ad3 = Integer.parseInt(SettingContext.getInofoSetting().getProperty("ad.3.cycle", "0"));
        int ad4 = Integer.parseInt(SettingContext.getInofoSetting().getProperty("ad.4.cycle", "0"));
        int ad5 = Integer.parseInt(SettingContext.getInofoSetting().getProperty("ad.5.cycle", "0"));

        String ad1_text = SettingContext.getInofoSetting().getProperty("ad.1.text", "");
        String ad2_text = SettingContext.getInofoSetting().getProperty("ad.2.text", "");
        String ad3_text = SettingContext.getInofoSetting().getProperty("ad.3.text", "");
        String ad4_text = SettingContext.getInofoSetting().getProperty("ad.4.text", "");
        String ad5_text = SettingContext.getInofoSetting().getProperty("ad.5.text", "");

        if (ad1 > 0 && !"".equals(ad1_text)) {
            if (this.time % ad1 == 0) {
                RobotContext.sendMsg(ad1_text);
            }
        }
        if (ad2 > 0 && !"".equals(ad2_text)) {
            if (this.time % ad2 == 0) {
                RobotContext.sendMsg(ad2_text);
            }
        }
        if (ad3 > 0 && !"".equals(ad3_text)) {
            if (this.time % ad3 == 0) {
                RobotContext.sendMsg(ad3_text);
            }
        }
        if (ad4 > 0 && !"".equals(ad4_text)) {
            if (this.time % ad4 == 0) {
                RobotContext.sendMsg(ad4_text);
            }
        }
        if (ad5 > 0 && !"".equals(ad5_text)) {
            if (this.time % ad5 == 0) {
                RobotContext.sendMsg(ad5_text);
            }
        }

        if (GameContext.autoStopBetting) {
            //轮换数据
            this.lastGameNo = gameNo;
            this.gameNo = nextGameNo;
            this.nextGameNo = this.gameNo + 1;
            GameContext.canPlay = true;
            GameContext.canBetting = true;
        }
        if (GameContext.canPlay) {
            newRound();
        }
    }

    /**
     * 处理下注结果
     *
     * @param betting 必须有下注情况
     * @param game    必须已经保存结果
     * @return 在此次下注获得的积分, 为0表示输了
     */
    public static double dealBettingResult(Betting betting, Game game) {
        BettingService bettingService = SpringContextUtil.getBean(BettingService.class);
        int result1 = game.getResult1();
        int result2 = game.getResult2();
        int result3 = game.getResult3();

        boolean duizi = GameContext.isDuizi(result1, result2, result3);
        boolean shunzi = GameContext.isShunzi(result1, result2, result3);
        Map<String, Double> result = GameContext.dealResult(result1, result2, result3);
        for (String c : result.keySet()) {
            if (c.equals(betting.getContent())) {//符合
                if (result1 + result2 + result3 == 13 || result1 + result2 + result3 == 14) {
                    if (!c.startsWith("特")) {//特码不需要判断总注,只为了确认13 14的赔率,所以不涉及豹子
                        //不是对子且不是顺子或者都没设置对应的赔率,则需要判断总注
                        if (!((duizi && SettingContext.getInfoSettingProperties("daxiaodanshuang.right.duizi.check", false)) || (shunzi && SettingContext.getInfoSettingProperties("daxiaodanshuang.right.shunzi.check", false)))) {
                            List<Betting> bettings = bettingService.queryBettingByGameAndMember(game.getId(), betting.getMember().getId());
                            double all = 0;//总注
                            for (Betting b : bettings) {
                                all += (b == null || b.getScore() == null ? 0 : b.getScore());
                            }

                            if ("大".equals(c) || "小".equals(c) || "单".equals(c) || "双".equals(c) || "极大".equals(c) || "极小".equals(c)) {//大小单双
                                if (SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu1.check", false)) {
                                    double setting = SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu1.text", 0);
                                    if (setting > 0 && setting < all) {
                                        double odd = SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu1.peilv", 0);
                                        if (odd > 0) {
                                            result.put(c, odd);
                                        }
                                    }
                                }
                                if (SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu2.check", false)) {
                                    double setting = SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu2.text", 0);
                                    if (setting > 0 && setting < all) {
                                        double odd = SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu2.peilv", 0);
                                        if (odd > 0) {
                                            result.put(c, odd);
                                        }
                                    }
                                }
                                if (SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu3.check", false)) {
                                    double setting = SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu3.text", 0);
                                    if (setting > 0 && setting < all) {
                                        double odd = SettingContext.getInfoSettingProperties("daxiaodanshuang.zongzhu3.peilv", 0);
                                        if (odd > 0) {
                                            result.put(c, odd);
                                        }
                                    }
                                }
                            }
                            if ("大单".equals(c) || "小单".equals(c) || "大双".equals(c) || "小双".equals(c)) {
                                if (SettingContext.getInfoSettingProperties("zuhe.zongzhu.1.check", false)) {
                                    double setting = SettingContext.getInfoSettingProperties("zuhe.zongzhu.1.text", 0);
                                    if (setting > 0 && setting < all) {
                                        double odd = SettingContext.getInfoSettingProperties("zuhe.zongzhu.1.text1", 0);
                                        if (odd > 0) {
                                            result.put(c, odd);
                                        }
                                    }
                                }
                                if (SettingContext.getInfoSettingProperties("zuhe.zongzhu.2.check", false)) {
                                    double setting = SettingContext.getInfoSettingProperties("zuhe.zongzhu.2.text", 0);
                                    if (setting > 0 && setting < all) {
                                        double odd = SettingContext.getInfoSettingProperties("zuhe.zongzhu.2.text1", 0);
                                        if (odd > 0) {
                                            result.put(c, odd);
                                        }
                                    }
                                }
                                if (SettingContext.getInfoSettingProperties("zuhe.zongzhu.3.check", false)) {
                                    double setting = SettingContext.getInfoSettingProperties("zuhe.zongzhu.3.text", 0);
                                    if (setting > 0 && setting < all) {
                                        double odd = SettingContext.getInfoSettingProperties("zuhe.zongzhu.3.text1", 0);
                                        if (odd > 0) {
                                            result.put(c, odd);
                                        }
                                    }
                                }
                            }
                        }

                    }
                }

                double odd = result.get(c);
                double get = betting.getScore() * odd;
                return get;
            }
        }
        return 0;
    }

    /**
     * 爬取一次数据
     * <p>
     * todo 如果爬取失败,能切换新的爬虫
     *
     * @return
     */
    public Map<String, Object> reptile() {
        try {
            BaseReptile reptile = getReptile();
            reptile.reptile();
            Map<String, Object> map = reptile.getResult();
            if (map.size() >= 6) {
                return map;
            } else {
                throw new Exception("让下面的catch到");
            }
        } catch (Exception e) {
            if (GameContext.isBeiJingBeiYong) {
                return null;
            } else {
                //切换爬虫
                reptile = ReptileContext.getBeijing28BeiYongReptile();
                GameContext.isBeiJingBeiYong = true;
                if (reptile == null) {
                    return null;//这里会被catch空指针,然后被截获要求手动开奖
                }
                return reptile();
            }
        }
    }

    /**
     * 获取当前使用的爬虫
     *
     * @return
     */
    public BaseReptile getReptile() {
        if (reptile == null) {
            reptile = ReptileContext.getBeijing28Reptile();
        }
        return reptile;
    }

    /**
     * 将字符串切割成字符串+数字
     *
     * @param str 如AA123
     * @return {"AA","123"}
     */
    public static String[] cutStrNum(String str) {
        if (str == null || "".equals(str)) {
            return new String[]{"", ""};
        }
        int firstNum = -1;
        for (int i = 0; i <= str.length(); i++) {
            String s = str.substring(i, i + 1);
            try {
                int x = Integer.parseInt(s);
                firstNum = i;
                break;
            } catch (Exception e) {
                //说明不是数字
            }
        }
        if (firstNum == -1) {
            return new String[]{str, ""};
        }
        String[] result = new String[2];
        result[0] = str.substring(0, firstNum);
        result[1] = str.substring(firstNum);
        return result;
    }
}
